/*
 * Special KMS API Implement
 *
 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */
#ifndef ENCLAVE_QTSM_SDK_KMS_H
#define ENCLAVE_QTSM_SDK_KMS_H

#include "signer.h"
#include "attestation.h"

#define URL_MAX_LEN             1024
#define CURL_TIME_OUT_MS        (10 * 1000)
#define HTTPS_OK                200

/* KMS API */
#define CREATE_DATAKEY          "create-datakey"
#define GEN_RANDOM              "gen-random"
#define DECRYPT_DATA            "decrypt-data"
/* Request method */
#define GET                     "GET"
#define POST                    "POST"

/* Payload options */
#define PAYLOAD_EXPAND_SIZE     300
/* Base64 limit */
#define BASE64_MIN_LEN          2

enum kms_errcode {
    KMS_SUCCESS = 0,
    KMS_COMMON_ERROR = 1,
    KMS_QTSM_ERROR = 2,
    KMS_REQ_PARAMS_ERROR = 3,
    KMS_HANDLE_EMPTY = 4,
    KMS_INTERNAL_ERROR = 5,
    KMS_BUFFS_EMPTY = 6,
    KMS_BUFFS_SMALL = 7,
    KMS_BUFFS_ERROR = 8,
    KMS_KEY_EMPTY = 9,
    KMS_UERDATA_EMPTY = 10,
    KMS_BASE64EN_ERROR = 11,
    KMS_BASE64DE_ERROR = 12,
    KMS_CURL_ERROR = 13,
    KMS_REQ_FAILED = 14,
    KMS_MALLOC_ERROR = 15,
    /* cjson failed to parse the response */
    KMS_CJSON_ERROR = 16,
    KMS_RSA_ERROR = 17,
    KMS_RESP_ERROR = 18,
    KMS_RESP_BUFF_SMALL = 19,
    KMS_OVERFLOW_ERROR = 20,
    KMS_INVALID_BASE64 = 21,
    KMS_GET_ATTESTATION_ERROR = 22,
};

typedef struct func_params_s {
    char* name;
    char* method;
} func_params_t;

typedef struct func_API_name_s {
    func_params_t generate_data_key;
    func_params_t generate_random;
    func_params_t decrypt_data;
    func_params_t encrypt_data;
} func_API_name_t;

typedef struct keyid_handle_s {
    char *key_id;
    unsigned int len;
} keyid_handle_t;

typedef struct datakey_s {
    char *key_id;
    unsigned int *key_id_len;
    unsigned char *plain_key;
    unsigned int *plain_key_len;
    unsigned char *cipher_key;
    unsigned int *cipher_key_len;
} datakey_t;

typedef struct random_data_s {
    unsigned char *random;
    unsigned int *random_len;
} random_data_t;

typedef struct plain_cipher_buff_s {
    const unsigned char *data_in;
    unsigned int data_in_len;
    unsigned char *data_out;
    unsigned int *data_out_len;
} plain_cipher_buff_t;

#ifdef SDK_DEBUG
#define qtsm_sdk_debug(format, ...) printf("Info:[%s:%s(%d)]:" format "\n", \
    __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define qtsm_sdk_debug(format, ...)
#endif

unsigned int extract_data_from_envelop(unsigned char *ciphertext,
    unsigned int ciphertext_len, struct rsa_keypair* keypair,
    struct stream_buf *plain_text);

/*
 * kms_generate_datakey_blocking() - Get data keys using huawei KMS API.
                               This function blocks and waits for the reply.
 * @sig_params (input) : The parameters to use for calling the API.
 * @handle (input) : The alias of KMS CMK used to encrypt the data key.
 * @datakey_len (input) : The spec of key to generate.
 * @datakey (output) : The keyid/plaintext/ciphertext_blob output of the call.
 *
 * Context: process context
 *
 * Returns: The status of the operation.
 */
unsigned long kms_generate_datakey_blocking(const sig_params_t *sig_params,
                                            const keyid_handle_t *handle,
                                            unsigned int datakey_len,
                                            datakey_t *datakey);

/*
 * kms_gen_random_blocking() - Get random numbers using huawei KMS API.
                               This function blocks and waits for the reply.
 * @sig_params (input) : The parameters to use for calling the API.
 * @random_len (input) : The number of random bytes to generate.
 * @random (output) : The plaintext output of the call.
 *
 * Context: process context
 *
 * Returns: The status of the operation.
 */
unsigned long kms_gen_random_blocking(const sig_params_t *sig_params,
    unsigned int random_len, random_data_t *random);

/*
 * kms_decrypt_data_blocking() - Decrypt data using huawei KMS API.
                               This function blocks and waits for the reply.
 * @sig_params (input) : The parameters to use for calling the API.
 * @handle (input) : The alias of KMS CMK used to decrypt data.
 * @data (input/output) : The ciphertext to decrypt (as input),
 *                          and the plaintext output as the call (as output).
 *
 * Context: process context
 *
 * Returns: The status of the operation.
 */
unsigned long kms_decrypt_data_blocking(const sig_params_t *sig_params,
                                        const keyid_handle_t *handle,
                                        plain_cipher_buff_t *data);

#endif
